package com.usian.article.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.usian.article.feign.AdminFeign;
import com.usian.article.service.ApArticleService;
import com.usian.article.service.HotArticleService;
import com.usian.model.admin.pojos.AdChannel;
import com.usian.model.article.pojos.ApArticle;
import com.usian.model.article.vo.HotArticleVO;
import com.usian.model.common.constants.ArticleConstans;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class HotArticleServiceImpl implements HotArticleService {


    @Autowired
    private ApArticleService apArticleService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private AdminFeign adminFeign;


    @Override
    public void computeHotArticle() {
        // 1.查询出前5天的文章
        String dayParam = DateTime.now().minusDays(5).toString("yyyy-MM-dd 00:00:00");

        List<ApArticle> apArticleList =
                apArticleService.list(Wrappers.<ApArticle>lambdaQuery().gt(ApArticle::getPublishTime, dayParam));
        if (apArticleList == null || apArticleList.isEmpty()) {
            log.info("当前时间前5天没有文章数据：{}", DateTime.now().toString("yyyy-MM-dd 00:00:00"));
            return;
        }
        // 2.计算文章分值
        List<HotArticleVO> hotArticleVOList = computeHotArticleScore(apArticleList);

        // 3.按照频道存入redis缓存中
        cacheAndSort(hotArticleVOList);

    }


    private void cacheAndSort(List<HotArticleVO> hotArticleVOList) {
        // 1.查询出所有的频道
        List<AdChannel> adChannelList =
                JSON.parseArray(JSON.toJSONString(adminFeign.findAll().getData()), AdChannel.class);

        // 2.各自取出各个频道的数据
        for (AdChannel channel : adChannelList) {
            List<HotArticleVO> channelHotList =
                    hotArticleVOList.stream()
                            .filter(x -> x.getChannelId().equals(channel.getId()))
                            .collect(Collectors.toList());
            // 排序   取前30条  放入redis中   key  hot_article_first_page_channelId   List<HotArticleVO>
            cacheChannelData(channelHotList, ArticleConstans.HOT_ARTICLE_FIRST_PAGE + channel.getId());
        }

        // 4.所有文章分值中最高的前30篇，存入缓存，对应推荐
        cacheChannelData(hotArticleVOList,
                ArticleConstans.HOT_ARTICLE_FIRST_PAGE + ArticleConstans.DEFAULT_TAG);
    }

    private void cacheChannelData(List<HotArticleVO> channelHotList, String key) {
        // 排序
        channelHotList.sort(new Comparator<HotArticleVO>() {
            @Override
            public int compare(HotArticleVO o1, HotArticleVO o2) {
                return o2.getScore().compareTo(o1.getScore());
            }
        });
        List<HotArticleVO> hotArticleVOList = null;
        if (channelHotList.size() < 30) {
            hotArticleVOList = channelHotList;
        } else {
            hotArticleVOList = channelHotList.subList(0, 30);
        }
        stringRedisTemplate.opsForValue().set(key, JSON.toJSONString(hotArticleVOList));
    }

    /**
     * 功能描述：计算每一篇文章分值
     * @param:
     * @return：
     * @auther：
     */
    private List<HotArticleVO> computeHotArticleScore(List<ApArticle> apArticleList) {
        List<HotArticleVO> resultList = new ArrayList<>();
        apArticleList.forEach(x -> {
            HotArticleVO hotArticleVO = new HotArticleVO();
            BeanUtils.copyProperties(x, hotArticleVO);
            // 计算文章分值
            Integer score = computeScore(x);
            hotArticleVO.setScore(score);
            resultList.add(hotArticleVO);
        });

        return resultList;
    }

    private Integer computeScore(ApArticle apArticle) {
        Integer score = 0;
        // 阅读
        if (apArticle.getViews() != null) {
            score += apArticle.getViews();
        }
        // 点赞
        if (apArticle.getLikes() != null) {
            score += apArticle.getLikes() * ArticleConstans.HOT_ARTICLE_LIKE_WEIGHT;
        }
        // 评论
        if (apArticle.getComment() != null) {
            score += apArticle.getComment() * ArticleConstans.HOT_ARTICLE_COMMENT_WEIGHT;
        }
        // 收藏
        if (apArticle.getCollection() != null) {
            score += apArticle.getCollection() * ArticleConstans.HOT_ARTICLE_COLLECTION_WEIGHT;
        }
        return score;
    }
}
